
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>函数的扩展</title>
</head>
<body>
     
    <!-- 
        1.扩展运算符(spread)    ...
            展开数据
            作用：数据合拼、数据拷贝、伪数组转数组
        2.rest(剩余)参数
            在不确定函数参数个数的情况下可以使用扩展运算符... 获取函数的剩余参数比较方便
            注意：rest得到的结果类型是数组,而arguments是伪数组
        3.箭头函数
            特点：
                1.一般函数可以先调用后定义，而箭头函数只能先定义后调用（和预解析有关）
                2.一般函数有arguments，而箭头函数没有arguments、但可以使用rest(剩余)参数；
                3.一般函数可以当作构造函数，而箭头函数不能当作构造函数，因为箭头函数没有自己的this；
                ​	依赖于外层环境中的this指向，并且是函数定义的时候确定的。
                4.当箭头函数只有一个形参时则可以省略圆括号； 
                5.当箭头函数只有一条语句并且该语句会作为返回值返回时，可以省略花括号及return关键词；
            箭头函数的不适用的场景：
                1)、对象中的方法不能直接使用箭头函数；
                2)、给DOM绑定事件时慎用箭头函数；
    -->


    <script>

        // 1.扩展运算符(spread)

        console.log(...[1,2,3,4,5]);
        console.log([10,20,[...[1,2,3,4,5]]]);//二维数组

        let o1 = { id: 11, name: "鲁班" }
        // 浅拷贝
        let o2 = {...o1}
        console.log(o2);
        
        // 2.rest(剩余)参数  接受多余的参数 转换为数组
        function add(...a) {
            console.log('收集到的函数参数是：',a);
            
        }

        add(1,2,3,4,5,6,7,8)
        

        // es6允许使用箭头来表示函数  =>  箭头函数  规范：不加小括号 一个参数   需要小括号 不需要参数及多个参数时
        // 3.箭头函数，只能使用匿名的方式来定义，不能使用声明式来定义
        // 特点：
        // 1.一般函数可以先调用后定义，而箭头函数只能先定义后调用（和预解析有关）
        // fn2()//我是声明式函数

        // function arrow(v) {
        //     return  10*v
        // }
        // let arrow = v => 10*v
        let arrow = (v) => {
           return 10*v
        }
        console.log(arrow(100));


         // 箭头函数与普通函数的区别
        // 1、定义不同：箭头函数使用箭头定义，普通函数用function定义。
        // 2、箭头函数全都是匿名函数：普通函数可以有匿名函数，也可以有具名函数
        // 3、箭头函数不能用于构造函数：普通函数可以用于构造函数，以此创建对象实例。
        // 4、箭头函数中 this 的指向不同：在普通函数中，this 总是指向调用它的对象，如果用作构造函数，它指向创建的对象实例。(箭头函数中的this指向父级作用域的上下文对象)
        // 5、箭头函数不具有 arguments 对象：每一个普通函数调用后都具有一个arguments 对象，用来存储实际传递的参数。但是箭头函数并没有此对象。
        // 6、其他区别：箭头函数不具有 prototype 原型对象。箭头函数不具有 super。箭头函数不具有 new.target


        // var  lives = 100;
        // const  cat = {
        //     lives: 9,
        //     // jumps:function(){
        //     //     return  this.lives--;//
        //     // }
        //     jumps:()=>{
        //         // console.log(this);               
        //         return  this.lives--;
        //     }
        // }

        // console.log(cat.jumps());//

        // var age = 10;
        // let obj = {
        //     age : 20,
        //     info:function(){
        //         return ()=>{
        //             console.log(this.age);//30
        //             console.log(this);//person
        //         }
        //     }
        // }

        // let info = obj.info()
        // info()


        // let person = {
        //     age : 30
        // }

        // // call(obj,,,,)   apply(obj,[,[]])  bind(obj,,,)()的区别   强制改变this指向
        // // let info2 = obj.info.call(person)
        // // let info2 = obj.info.apply(person)
        // let info2 = obj.info.bind(person)(this)

        // info2()


        function foo() {
            id:80,
            setTimeout(() => {
                console.log("id:",this.id);//100
                console.log(this);//window
                
            }, 100);
        }

        var id = 100;
        foo({id:50})//
        foo.bind({id:50})(this)//
        

        // 函数的尾调用
        function fn(x) {
            console.log("hello " + x);
            
        }
        function fn1(y) {
           return fn(y)  //函数的尾调用
        }

        fn1("jack")

        
    </script>
</body>
</html>